import asyncore
import socket
import pickle
from .port_name import PORT
from .watcher_schema import schema
from . import message


class AffectedHandler(asyncore.dispatcher_with_send):

  def __init__(self, sock, watcher):
    super().__init__(sock)
    self.watcher = watcher
    self.pending = []

  def watch(self, context, files):
    print("watching : " + repr(files))
    for fname in files:
      self.watcher.watch(fname)
    return context.ack()

  def unwatch(self, context, files):
    print("unwatching : " + repr(files))
    for fname in files:
      self.watcher.unwatch(fname)
    return context.ack()

  def drop(self, context, files):
    print("dropping : " + repr(files))
    for fname in files:
      self.watcher.drop_changes(fname)
    return context.ack()

  def unlock(self, context):
    if self.watcher.locked != self:
      return context.not_yours()
    self.watcher.locked = None
    if(len(self.pending)):
      o_context = self.pending.pop()
      o_context.aquired()
    return context.ack()

  def lock(self, context):
    if not self.watcher.locked:
      self.watcher.locked = self
      return context.aquired()
    self.pending.append(context)

  def ack_affected(self, context):
    self.watcher.ack_affected()
    return context.ack()

  def get_affected(self, context):
    targets = self.watcher.get_affected()
    print("affected: " + repr(targets))
    return context.targets(targets)

  def handle_read(self):
    schema.handle(self)

  def close(self):
    super().close()
    if self.watcher.locked == self:
      print("someone forgot to unlock this")
      self.watcher.locked = None
    

class AffectedServer(asyncore.dispatcher):

  def __init__(self, watcher):
    asyncore.dispatcher.__init__(self)
    self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
    self.set_reuse_addr()
    self.bind(("localhost", 0))
    with open("bin/__graph__/watcher_port", "w+") as f:
      f.write(str(self.getsockname()[1]))

    self.listen(5)
    self.watcher = watcher

  def handle_accept(self):
    pair = self.accept()
    if pair is not None:
      sock, addr = pair
      print('Incoming connection from %s' % repr(addr))
      handler = AffectedHandler(sock, self.watcher)

